package band.wukong.practice.javase.core.thread.sync;

/**
 * Desc: 生产者与消费者的问题
 * Author: sunjs
 * Date: 2009-11-5 16:55:55
 */
public class TestProducerAndConsumer {
    protected static final int LOOP_TIMES = 100;

    public static void main(String[] args) {
        Stack stack = new Stack("stack");
        Producer producer01 = new Producer(stack, "producer01");
        Producer producer02 = new Producer(stack, "producer02");
        Consumer consumer01 = new Consumer(stack, "consumer01");
//        Consumer consumer02 = new Consumer(stack, "consumer02");
    }
}

class Producer extends Thread {
    private Stack stack;

    public Producer(Stack s, String name) {
        super(name);
        stack = s;
        start();
    }

    public void run() {
        String goods;
        for (int i = 0; i < TestProducerAndConsumer.LOOP_TIMES; i++) {
            synchronized (stack) {
                goods = "goods" + (stack.getPoint() + 1);
                stack.push(goods);
                System.out.println(getName() + ": push " + goods);
            }
        }
    }
}

class Consumer extends Thread {
    private Stack stack;

    public Consumer(Stack s, String name) {
        super(name);
        stack = s;
        start();
    }

    public void run() {
        String goods = null;
        for (int i = 0; i < TestProducerAndConsumer.LOOP_TIMES; i++) {
            goods = stack.pop();
            System.out.println(getName() + ": pop " + goods + " from " + stack.getName());
            yield();
        }
    }
}

class Stack {
    int point = -1;
    private String name;
    private String[] buffer = new String[200];

    public Stack(String name) {
        this.name = name;
    }

    public synchronized String pop() {
        String goods = buffer[point];
        buffer[point] = null;
        Thread.yield();
        point--;
        return goods;
    }

    public synchronized void push(String goods) {
        point++;
        Thread.yield();
        buffer[point] = goods;
    }

    public String getName() {
        return name;
    }

    public synchronized int getPoint() {
        return point;
    }
}
